<template>
  <picker
    mode="multiSelector"
    :range="addressRange"
    range-key="name"
    @change="pickerChange"
    @columnchange="columnchange"
    :value="pickerValue"
    @cancel="$emit('cancel')"
    :disabled="disabled"
  >
    <slot v-if="$slots.default"></slot>
    <input v-else type="text" :value="inputStr" disabled placeholder="请选择">
  </picker>
</template>

<script>
import address from "../../utils/address.json";  // 可注释 注释此行请删除utils目录下的address.json文件
export default {
  /**
   * @param modelValue Array(string) ['四川省', '成都市', '武侯区']
   * @param codeValue Array(string | number) [ "51","5101", "510107" ]
   * @param selectIndex Array(number) [ 0, 0, 0 ]
   * @param disabled 禁用
   * @param loadJson 自定义加载地址json
  */
  props: {
    modelValue: Array,
    value: Array,
    codeValue: Array,
    disabled: {
      type: Boolean,
      default: false,
    },
    selectIndex: {
      type: Array,
      default: () => [0, 0, 0],
    },
    loadJson: {
      type: Function,
    }
  },
  model: {
    prop: 'value',
    event: 'input'
  },
  emits: [
    "update:modelValue",
    "update:codeValue",
    "columnchange",
    "change",
    "cancel",
    "input",
  ],
  computed: {
    inputStr() {
      if (this._value && this._value.length !== 0) {
        return Array.from(new Set(this._value || [])).join('');
      }
      if (this.value && this.value.length !== 0) {
        return Array.from(new Set(this.value || [])).join('');
      }
    },
    _value() {
      return this.value || this.modelValue;
    }
  },
  data() {
    return {
      addressRange: [],
      pickerValue: [0, 0, 0],
    };
  },
  async created() {
    this.pickerValue = [...this.selectIndex];
    if (this.loadJson) {
      const addressJson = await this.loadJson();
      if (!Array.isArray(addressJson)) {
        throw new Error('loadJson 必须返回数组');
      }
      this.addressRange[0] = addressJson
      console.warn('<sh-address> 您已自定义地址json, 请删除插件源码中指定可删除代码, 以减小应用体积');
    } else {
      this.addressRange[0] = address; // 可注释
    }
    this.setDefByCode();
    this.setDefByName();
  },
  watch: {
    _value() {
      this.setDefByName();
    },
    codeValue() {
      this.setDefByCode();
    },
  },
  methods: {
    columnchange(e) {
      const { column, value } = e.detail;
      this.$emit("columnchange", e.detail);
      if (column === 0) {
        this.addressRange[1] = this.addressRange[0][value].child;
        this.addressRange[2] = this.addressRange[1]?.[this.pickerValue[1]]?.child || this.addressRange[1][0].child || [];
      }
      if (column === 1) {
        this.addressRange[2] = this.addressRange[1][value].child;
      }
      this.$forceUpdate()
    },
    pickerChange(e) {
      const v = e.detail.value;
      const { name: province, code: provinceCode } = this.addressRange[0][v[0]];
      const { name: city, code: cityCode } = this.addressRange[1][v[1]];
      const {
        code: areaCode,
        name: area,
      } = this.addressRange[2][v[2]];
      this.$emit("change", {
        areaCode,
        area,
        cityCode,
        provinceCode,
        province,
        city,
      });
      this.$emit("input", Array.from(new Set([province, city, area])));
      this.$emit("update:modelValue", Array.from(new Set([province, city, area])));
      this.$emit("update:codeValue", Array.from(new Set([provinceCode, cityCode, areaCode])));
    },
    setDefByCode() {
      if (this.codeValue instanceof Array && this.codeValue.length >= 1) {
        const provinceIndex = this.addressRange[0].findIndex(
          (item) => item.code === this.codeValue[0].toString()
        );
        if (provinceIndex === -1) {
          this.addressRange[1] = this.addressRange[0][0].child;
          this.addressRange[2] = this.addressRange[1][0].child;
          return;
        }
        this.addressRange[1] = this.addressRange[0][provinceIndex].child;

        const cityIndex = this.addressRange[1].findIndex(
          (item) => item.code === this.codeValue[1]?.toString()
        );
        if (cityIndex === -1) {
          this.addressRange[2] = this.addressRange[1][0].child;
          this.$nextTick(() => {
            this.pickerValue = [provinceIndex, 0, 0];
          });
          return;
        }
        this.addressRange[2] = this.addressRange[1][cityIndex].child;

        const areaIndex = this.addressRange[2].findIndex(
          (item) => item.code === this.codeValue[2]?.toString()
        );
        if (areaIndex === -1) {
          this.$nextTick(() => {
            this.pickerValue = [provinceIndex, cityIndex, 0];
          });
          return;
        }
        this.$nextTick(() => {
          this.pickerValue = [provinceIndex, cityIndex, areaIndex];
        });
      } else {
        this.addressRange[1] = this.addressRange[0][0].child;
        this.addressRange[2] = this.addressRange[1][0].child;
      }
    },
    setDefByName() {
      if (this._value instanceof Array && this._value.length >= 1) {
        const provinceIndex = this.addressRange[0].findIndex(
          (item) => item.name === this._value[0]
        );
        if (provinceIndex === -1) {
          this.addressRange[1] = this.addressRange[0][0].child;
          this.addressRange[2] = this.addressRange[1][0].child;
          return;
        }
        this.addressRange[1] = this.addressRange[0][provinceIndex].child;

        const cityIndex = this.addressRange[1].findIndex(
          (item) => item.name === this._value[1]
        );
        if (cityIndex === -1) {
          this.addressRange[2] = this.addressRange[1][0].child;
          this.$nextTick(() => {
            this.pickerValue = [provinceIndex, 0, 0];
          });
          return;
        }
        this.addressRange[2] = this.addressRange[1][cityIndex].child;

        const areaIndex = this.addressRange[2].findIndex(
          (item) => item.name === this._value[2]
        );
        if (areaIndex === -1) {
          this.$nextTick(() => {
            this.pickerValue = [provinceIndex, cityIndex, 0];
          });
          return;
        }
        this.$nextTick(() => {
          this.pickerValue = [provinceIndex, cityIndex, areaIndex];
        });
      } else {
        this.addressRange[1] = this.addressRange[0][0].child;
        this.addressRange[2] = this.addressRange[1][0].child;
      }
    },
  },
};
</script>
